package at.fhj.swd.pse.data;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TransactionRequiredException;

import at.fhj.swd.pse.entities.Community;
import at.fhj.swd.pse.entities.User;
import at.fhj.swd.pse.exceptions.PortalException;

/**
 * Use this implementation of community DAO to access community objects
 * 
 * @author Helmut Kopf
 * @author Robert Puerer
 * 
 */

@Stateless
public class CommunityDAOImpl implements CommunityDAO {
	@PersistenceContext
	private EntityManager m_em;

	public CommunityDAOImpl(final EntityManager em) {
		if (em != null) {
			this.m_em = em;
		} 
		else {
			throw new NullPointerException("em");
		}
	}
	
	public CommunityDAOImpl()
	{
	}

	@Override
	public Community insert(Community community) {
		if (community != null) {
			try
			{
				return m_em.merge(community);
			}
			catch (IllegalArgumentException ex)
			{								
				throw new PortalException("Instance is not an entity or is a removed entity!", ex);
			}
			catch (TransactionRequiredException ex)
			{								
				throw new PortalException("Invokation on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction!", ex);
			}						 		
		} 
		else {
			throw new NullPointerException("community");
		}
	}

	@Override
	public Community get(int id) {
		return m_em.find(Community.class, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Community> getAll() {
		try
		{
			final String hql = "SELECT c FROM Community AS c";
			return m_em.createQuery(hql).getResultList();
		}
		catch (IllegalArgumentException ex)
		{								
			throw new PortalException("The query string is invalid!", ex);
		}		
	}

	@Override
	public void remove(Community community) {
		if (community != null) {			
			try
			{
				m_em.remove(community);
			}
			catch (IllegalArgumentException ex)
			{								
				throw new PortalException("Instance is not an entity or is a removed entity!", ex);
			}
			catch (TransactionRequiredException ex)
			{								
				throw new PortalException("Invokation on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction!", ex);
			}						 		
		} 
		else {
			throw new NullPointerException("community");
		}
	}
	
	@Override
	public Community update(Community community) {
		if (community != null) {			
			try
			{
				m_em.merge(community);
				return community;
			}
			catch (IllegalArgumentException ex)
			{								
				throw new PortalException("Instance is not an entity or is a removed entity!", ex);
			}
			catch (TransactionRequiredException ex)
			{								
				throw new PortalException("Invokation on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction!", ex);
			}						 		
			
		} 
		else {
			throw new NullPointerException("community");
		}
		
	}

	@Override
	public void addUserToCommunity(int userId, int communityId) {		
		try
		{
			Community community = m_em.find(Community.class, communityId);
			User user = m_em.find(User.class, userId);
			
			if (!community.contains(user))
			{
				community.addMember(user);
			}
			else
			{
				throw new IllegalArgumentException("User is already member of this community!");
			}
		}
		catch (IllegalArgumentException ex)
		{								
			throw new PortalException("The first argument does not denote an entity type or the second argument is is not a valid type for that entity!", ex);
		}		
	}
	
	@Override
	public void releaseCommunity(int communityId) {
		Community community = m_em.find(Community.class, communityId);
		community.setReleased(true);
		
		update( community );
	}
}
